package com.googlecode.cswish.util.lucene;

import java.io.File;
import java.io.IOException;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.RAMDirectory;
import org.hibernate.search.SearchException;
import org.hibernate.search.indexes.impl.DirectoryBasedIndexManager;
import org.hibernate.search.spi.BuildContext;
import org.hibernate.search.store.DirectoryProvider;
import org.hibernate.search.store.impl.DirectoryProviderHelper;


public class RAMFSDirectoryProvider implements DirectoryProvider<RAMDirectory> {

	private final static Logger logger = Logger.getLogger(RAMFSDirectoryProvider.class);

	private FSDirectory directory;
	
	private RAMDirectory ramDirectory;
	private String indexName;
	private Properties properties;

	@Override
	public void start(DirectoryBasedIndexManager indexManager) {
		
	}
	
	public void initialize(String directoryProviderName, Properties properties, BuildContext context) {
		indexName = directoryProviderName;
		this.properties = properties;
		
		// on "manual" indexing skip read-write check on index directory
		boolean manual = context.getIndexingStrategy().equals( "manual" );
		File indexDir = DirectoryProviderHelper.getVerifiedIndexDir( directoryProviderName, properties, !manual );
		try {
			indexName = indexDir.getCanonicalPath();
			//this is cheap so it's not done in start()
			directory = DirectoryProviderHelper.createFSIndex( indexDir, properties );
			ramDirectory = new RAMDirectory();
		}
		catch ( IOException e ) {
			throw new SearchException( "Unable to initialize index: " + directoryProviderName, e );
		}
	}
	
//	private void sync() {
//		// http://apps.hi.baidu.com/share/detail/12898177
//		IndexWriter fswriter=new IndexWriter(fsdir,newSimpleAnalyzer(),true);
//		fswriter.addIndexes(new Directory[] {ramDirectory});
//		fswriter.flush();  
//		fswriter.close();
//	}

	public void start() {
		try {
			directory.setLockFactory( DirectoryProviderHelper.createLockFactory( null, properties ) );
			properties = null;
			DirectoryProviderHelper.initializeIndexIfNeeded( directory );
		}
		catch (IOException e) {
			throw new SearchException( "Unable to initialize index: " + indexName, e );
		}
	}
	
	public RAMDirectory getDirectory() {
		return ramDirectory;
	}
	
	public void stop() {
		try {
			ramDirectory.close();
			directory.close();
		}
		catch ( Exception e ) {
			logger.error( "Unable to properly close Lucene directory {}" + directory.getDirectory(), e );
		}
	}
	
	@Override
	public boolean equals(Object obj) {
		// this code is actually broken since the value change after initialize call
		// but from a practical POV this is fine since we only call this method
		// after initialize call
		if ( obj == this ) return true;
		if ( obj == null || !( obj instanceof RAMFSDirectoryProvider ) ) return false;
		return indexName.equals( ( (RAMFSDirectoryProvider) obj ).indexName );
	}

	@Override
	public int hashCode() {
		// this code is actually broken since the value change after initialize call
		// but from a practical POV this is fine since we only call this method
		// after initialize call
		int hash = 7;
		return 29 * hash + indexName.hashCode();
	}
}
